package com.qqt.csr.order.service.statemachine.rule;

import com.alibaba.cola.statemachine.StateMachine;
import com.alibaba.cola.statemachine.StateMachineFactory;
import com.alibaba.cola.statemachine.builder.StateMachineBuilder;
import com.alibaba.cola.statemachine.builder.StateMachineBuilderFactory;
import com.qqt.csr.order.enums.StateMachineIdEnum;
import com.qqt.csr.order.enums.WorkOrderEventEnum;
import com.qqt.csr.order.enums.WorkOrderStatusEnum;
import com.qqt.csr.order.service.statemachine.action.DefaultWorkOrderAction;
import com.qqt.csr.order.service.statemachine.condition.DefaultWorkOrderCondition;
import com.qqt.csr.order.service.statemachine.context.WorkOrderContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class WorkOrderStateMachineRule implements InitializingBean {
    @Autowired
    private DefaultWorkOrderCondition defaultWorkOrderCondition;
    @Autowired
    private DefaultWorkOrderAction defaultWorkOrderAction;

    /**
     * 初始化工单状态机
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        init();
        StateMachine<WorkOrderStatusEnum, WorkOrderEventEnum, WorkOrderContext> stateMachine = this.getStateMachine();
        log.info("工单状态机初始化完成，状态机id：{}，状态机UML：{}", stateMachine.getMachineId(), stateMachine.generatePlantUML());
    }

    /**
     * 获取工单状态机
     *
     * @return
     */
    public StateMachine<WorkOrderStatusEnum, WorkOrderEventEnum, WorkOrderContext> getStateMachine() {
        return StateMachineFactory.get(StateMachineIdEnum.WORK_ORDER.getCode());
    }

    /**
     * 工单状态机配置规则
     *
     * @return
     */
    private void init() {
        StateMachineBuilder<WorkOrderStatusEnum, WorkOrderEventEnum, WorkOrderContext> builder = StateMachineBuilderFactory.create();

        defineTransition(builder, WorkOrderStatusEnum.NONE, WorkOrderStatusEnum.TO_CLAIM, WorkOrderEventEnum.CREATED);
        defineTransition(builder, WorkOrderStatusEnum.NONE, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.CREATED_ALLOCATED);
        defineTransition(builder, WorkOrderStatusEnum.TO_CLAIM, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.RECEIVED);
        defineTransition(builder, WorkOrderStatusEnum.TO_CLAIM, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.ALLOCATED);
        defineTransition(builder, WorkOrderStatusEnum.TO_CLAIM, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.EDIT_ALLOCATED);
        defineTransition(builder, WorkOrderStatusEnum.TO_PROCESS, WorkOrderStatusEnum.SUSPENDED, WorkOrderEventEnum.SUSPENDED);
        defineTransition(builder, WorkOrderStatusEnum.SUSPENDED, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.RECOVERED);
        defineTransition(builder, WorkOrderStatusEnum.TO_PROCESS, WorkOrderStatusEnum.COMPLETED, WorkOrderEventEnum.COMPLETED);
        defineTransition(builder, WorkOrderStatusEnum.COMPLETED, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.REOPENED);
        defineTransition(builder, WorkOrderStatusEnum.TO_PROCESS, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.UPDATED_DESIGNEE);
        defineTransition(builder, WorkOrderStatusEnum.TO_PROCESS, WorkOrderStatusEnum.TO_PROCESS, WorkOrderEventEnum.EDITED);
        defineTransition(builder, WorkOrderStatusEnum.TO_CLAIM, WorkOrderStatusEnum.TO_CLAIM, WorkOrderEventEnum.EDITED);
        for (WorkOrderStatusEnum workOrderStatus : WorkOrderStatusEnum.values()) {
            // 任何状态下都能删除
            defineTransition(builder, workOrderStatus, workOrderStatus, WorkOrderEventEnum.DELETED);
        }

        builder.build(StateMachineIdEnum.WORK_ORDER.getCode());
    }

    private void defineTransition(StateMachineBuilder<WorkOrderStatusEnum, WorkOrderEventEnum, WorkOrderContext> builder,
                                  WorkOrderStatusEnum from, WorkOrderStatusEnum to, WorkOrderEventEnum event) {
        if (from.equals(to)) {
            builder.internalTransition().within(to).on(event).when(defaultWorkOrderCondition).perform(defaultWorkOrderAction);
        } else {
            builder.externalTransition().from(from).to(to).on(event).when(defaultWorkOrderCondition).perform(defaultWorkOrderAction);
        }
    }


}
